#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/split.hpp>

#include "gstviewer.h"

GstViewer::GstViewer(const char *url) {
    //Gtk::DrawingArea::DrawingArea(); // this is shit to remove
    this->xwin = 0;
    this->url = url;
    this->change_resolution = false;
    this->unset_flags(Gtk::DOUBLE_BUFFERED);
    this->video_init();
    this->show();
}


GstViewer::~GstViewer() {
    
}


bool GstViewer::on_expose_event(GdkEventExpose* event) {
    //Gtk::DrawingArea::on_expose_event(event); // this is shit to remove
    
    if (this->xwin == 0) {
        this->xwin = GDK_WINDOW_XID(this->get_window()->gobj());
        gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(this->vsink), this->xwin);
        cout << "xid " << this->xwin << endl;
        //Glib::Thread *this_thread =
        Glib::Thread::create(sigc::mem_fun(this, &GstViewer::video_start), false);
        //gst_element_set_state(this->bin, GST_STATE_PLAYING);
    }
    
    if(__sync_bool_compare_and_swap(&this->change_resolution, true, false)) {
    //if (this->change_resolution) {
        //this->change_resolution = false;
        cout << "width " << this->width << " height " << this->height << endl;
        this->set_size_request(this->width, this->height);
        this->queue_resize();
        
    }
    return true;
}

void GstViewer::video_start() {
    gst_element_set_state(this->bin, GST_STATE_PLAYING);
}

void GstViewer::video_init() {
    GstElement	*httpsrc;
    GstElement	*cps;
    GstPad		*pad;
    GError		*error = NULL;
    
    string ast;
    vector< string > svec;
    boost::algorithm::split( svec, url, boost::algorithm::is_any_of("://") );
    if (svec[0] == "v4l") {
        ast = "v4lsrc device=/dev/" + svec[3] + " name = source ! "\
                "ffmpegcolorspace name=fcps ! "\
                "ximagesink name=vsink";
        
    } else if (svec[0] == "http") {
        // neonhttpsrc location=http://localhost:4481 ! multipartdemux
        // autoscan=true ! jpegdec ! ffmpegcolorspace ! ximagesink
        ast = "neonhttpsrc name=source location=" + url + " ! "\
                "multipartdemux autoscan=true name=mpdex ! "\
                "jpegdec name=jpegdec ! "\
                "ffmpegcolorspace name=fcps ! "\
                "ximagesink name=vsink";
    }
    printf("%s\n", ast.c_str());
    this->bin = (GstElement *) gst_parse_launch(ast.c_str() , &error);
    
    GstBus *bus;
    bus = gst_pipeline_get_bus(GST_PIPELINE(this->bin));
    httpsrc = gst_bin_get_by_name(GST_BIN(this->bin), "source");
    cps = gst_bin_get_by_name(GST_BIN(this->bin), "fcps");
    this->vsink = gst_bin_get_by_name(GST_BIN(this->bin), "vsink");
    //g_object_set (this->vsink, "force-aspect-ratio", gboolean (TRUE), NULL);
    //g_object_set(httpsrc, "location", "http://192.168.0.200:4482/", NULL);
    //g_object_set(httpsrc, "location", "http://80.21.49.14/axis-cgi/mjpg/video.cgi?resolution=352x288&camera=1&dummy=garb", NULL);
    
    pad = gst_element_get_pad(vsink, "sink");
    if (!pad) cout << "TOOOO\n";
    g_signal_connect(G_OBJECT(pad), "notify::caps",
            G_CALLBACK(GstViewer::padlink), this);
    //gst_element_set_state (this->bin, GST_STATE_NULL);
}


void GstViewer::padlink(GstPad *pad, GstPad *peer, gpointer user_data) {
    GstViewer *asd  = (GstViewer*) user_data;
    cout << "padlink" << endl;
    asd->read_video_props(pad);
}


void GstViewer::read_video_props(GstPad *pad) {
    const GstStructure *str;
    GstCaps		*caps;
    gint width, height;
    
    cout << "read_video_props" << endl;
    
    pad = gst_element_get_pad(vsink, "sink");
    caps = gst_pad_get_negotiated_caps(pad);
    
    g_return_if_fail(gst_caps_is_fixed(caps));
    
    str = gst_caps_get_structure(caps, 0);
    if (!gst_structure_get_int(str, "width", &width) ||
            !gst_structure_get_int(str, "height", &height)) {
        g_print("No width/height available\n");
        return;
    }
    
    this->width = width;
    this->height = height;
    //this->set_size_request(this->width, this->height);
    this->change_resolution = true;
    
    
    //Glib::Mutex::Lock lock (this->mutex);
    //this->queue_resize();
    this->queue_draw();
    //ghghasd->queue_draw();
    //lock.release();
    
}
